name: Main Workflow
on: [push, pull_request]
env:
  LLVM_VERSION: 15
jobs:
  debug:
    if: github.event_name == 'push'
    runs-on: ubuntu-latest
    strategy:
      matrix:
        toolchain: ['clang', 'gcc']
        include:
          - toolchain: gcc
            c-compiler: gcc
            cxx-compiler: g++
          - toolchain: clang
            c-compiler: clang
            cxx-compiler: clang++
    steps:
      - uses: actions/checkout@v3
      - run: |
          wget https://apt.llvm.org/llvm.sh
          chmod +x llvm.sh
          sudo ./llvm.sh $LLVM_VERSION
          sudo apt update -y && sudo apt upgrade -y
          sudo apt-get -y install gcc-multilib g++-multilib clang-tidy-$LLVM_VERSION
          sudo update-alternatives --install /usr/bin/clang-tidy clang-tidy /usr/bin/clang-tidy-$LLVM_VERSION 50
          clang-tidy --version
      - run: >
          cmake
          -B ${{ github.workspace }}/build
          -DCMAKE_BUILD_TYPE=Debug
          -DCMAKE_C_COMPILER=${{ matrix.c-compiler }}
          -DCMAKE_CXX_COMPILER=${{ matrix.cxx-compiler }}
          tests
      - working-directory: ${{github.workspace}}/build
        run: |
          make VERBOSE=1
          make test
      - uses: actions/upload-artifact@v3
        if: always()
        with:
          name: ${{github.job}}
          path: ${{github.workspace}}/**/*
          retention-days: 2

  optimizations:
    if: github.event_name == 'push'
    runs-on: ubuntu-latest
    strategy:
      matrix:
        toolchain: ['clang', 'gcc']
        build_type: [Release, MinSizeRel]
        include:
          - toolchain: gcc
            c-compiler: gcc
            cxx-compiler: g++
          - toolchain: clang
            c-compiler: clang
            cxx-compiler: clang++
    steps:
      - uses: actions/checkout@v3
      - run: |
          sudo apt update -y && sudo apt upgrade -y
          sudo apt install gcc-multilib g++-multilib
      - run: >
          cmake
          -B ${{ github.workspace }}/build
          -DCMAKE_BUILD_TYPE=${{ matrix.build_type }}
          -DCMAKE_C_COMPILER=${{ matrix.c-compiler }}
          -DCMAKE_CXX_COMPILER=${{ matrix.cxx-compiler }}
          -DNO_STATIC_ANALYSIS=1
          tests
      - working-directory: ${{github.workspace}}/build
        run: |
          make VERBOSE=1
          make test
      - uses: actions/upload-artifact@v3
        if: always()
        with:
          name: ${{github.job}}
          path: ${{github.workspace}}/**/*
          retention-days: 2

  avr:
    if: github.event_name == 'push'
    runs-on: ubuntu-latest
    env:
      mcu: at90can64
      flags: -Wall -Wextra -Werror -pedantic -Wconversion -Wtype-limits
    steps:
      - uses: actions/checkout@v3
      - run: |
          sudo apt update -y && sudo apt upgrade -y
          sudo apt install gcc-avr avr-libc
          avr-gcc --version
      - run: avr-gcc libcanard/*.c -c -std=c99 -mmcu=${{ env.mcu }} ${{ env.flags }}
      - run: avr-gcc libcanard/*.c -c -std=c11 -mmcu=${{ env.mcu }} ${{ env.flags }}
      - run: avr-gcc libcanard/*.c -c -std=gnu99 -mmcu=${{ env.mcu }} ${{ env.flags }}
      - run: avr-gcc libcanard/*.c -c -std=gnu11 -mmcu=${{ env.mcu }} ${{ env.flags }}

  arm:
    if: github.event_name == 'push'
    runs-on: ubuntu-latest
    env:
      flags: -Wall -Wextra -Werror -pedantic -Wconversion -Wtype-limits -Wcast-align -Wfatal-errors
    steps:
      - uses: actions/checkout@v3
      - run: |
          sudo apt update -y && sudo apt upgrade -y
          sudo apt-get install -y gcc-arm-none-eabi
      - run: arm-none-eabi-gcc libcanard/*.c -c -std=c99 ${{ env.flags }}
      - run: arm-none-eabi-gcc libcanard/*.c -c -std=c11 ${{ env.flags }}

  style_check:
    if: github.event_name == 'push'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: DoozyX/clang-format-lint-action@v0.15
        with:
          source: './libcanard ./tests'
          exclude: './tests/catch'
          extensions: 'c,h,cpp,hpp'
          clangFormatVersion: ${{ env.LLVM_VERSION }}

  sonarcloud:
    if: >
      github.event_name == 'pull_request'                   ||
      contains(github.ref, '/master')                       ||
      contains(github.ref, '/release')                      ||
      contains(github.event.head_commit.message, '#sonar')
    runs-on: ubuntu-latest
    env:
      SONAR_SCANNER_VERSION: 4.8.0.2856
      SONAR_SERVER_URL: "https://sonarcloud.io"
      BUILD_WRAPPER_OUT_DIR: build_wrapper_output_directory
      GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
    steps:
    - uses: actions/checkout@v3
      with:
        fetch-depth: 0

    - name: Install Dependencies
      run: |
        sudo apt update -y && sudo apt upgrade -y
        sudo apt install -y gcc-multilib g++-multilib

    - name: Set up JDK
      uses: actions/setup-java@v3
      with:
        java-version: 11
        distribution: zulu

    - name: Cache SonarCloud packages
      uses: actions/cache@v3
      with:
        path: ~/.sonar/cache
        key: ${{ runner.os }}-sonar
        restore-keys: ${{ runner.os }}-sonar

    - name: Download and set up sonar-scanner
      env:
        SONAR_SCANNER_DOWNLOAD_URL: https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-${{ env.SONAR_SCANNER_VERSION }}-linux.zip
      run: |
        mkdir -p $HOME/.sonar
        curl -sSLo $HOME/.sonar/sonar-scanner.zip ${{ env.SONAR_SCANNER_DOWNLOAD_URL }}
        unzip -o $HOME/.sonar/sonar-scanner.zip -d $HOME/.sonar/
        echo "$HOME/.sonar/sonar-scanner-${{ env.SONAR_SCANNER_VERSION }}-linux/bin" >> $GITHUB_PATH

    - name: Download and set up build-wrapper
      env:
        BUILD_WRAPPER_DOWNLOAD_URL: ${{ env.SONAR_SERVER_URL }}/static/cpp/build-wrapper-linux-x86.zip
      run: |
        curl -sSLo $HOME/.sonar/build-wrapper-linux-x86.zip ${{ env.BUILD_WRAPPER_DOWNLOAD_URL }}
        unzip -o $HOME/.sonar/build-wrapper-linux-x86.zip -d $HOME/.sonar/
        echo "$HOME/.sonar/build-wrapper-linux-x86" >> $GITHUB_PATH

    - name: Run build-wrapper
      run: |
        cmake tests -DCMAKE_BUILD_TYPE=Debug -DNO_STATIC_ANALYSIS=1 -DCMAKE_C_FLAGS='-DNDEBUG=1'
        build-wrapper-linux-x86-64 --out-dir ${{ env.BUILD_WRAPPER_OUT_DIR }} make all
        make test
        gcov --preserve-paths --long-file-names $(find CMakeFiles/test_private_cov.dir    -name '*.gcno')
        gcov --preserve-paths --long-file-names $(find CMakeFiles/test_public_cov.dir     -name '*.gcno')

    - name: Run sonar-scanner
      # Don't run sonar-scanner on builds originating from forks due to secrets not being available
      run: >
        [ -z "$SONAR_TOKEN" ] || sonar-scanner
        --define sonar.organization=opencyphal
        --define sonar.projectName=libcanard
        --define sonar.projectKey=libcanard
        --define sonar.sources=libcanard
        --define sonar.exclusions=libcanard/_canard_cavl.h
        --define sonar.cfamily.gcov.reportsPath=.
        --define sonar.cfamily.build-wrapper-output="${{ env.BUILD_WRAPPER_OUT_DIR }}"
        --define sonar.host.url="${{ env.SONAR_SERVER_URL }}"

    - uses: actions/upload-artifact@v3
      if: always()
      with:
        name: ${{github.job}}
        path: ${{github.workspace}}/**/*
        retention-days: 2
